/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package LDAPAPI;

import LDAPAPI.Exceptions.LDAPActionException;
import java.util.LinkedList;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.ldap.ErrorResultException;
import org.forgerock.opendj.ldap.ErrorResultIOException;
import org.forgerock.opendj.ldap.LDAPConnectionFactory;
import org.forgerock.opendj.ldap.LinkedHashMapEntry;
import org.forgerock.opendj.ldap.SearchResultReferenceIOException;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldif.ConnectionEntryReader;

/**
 *
 * @author anvil
 */
public class AnvilLDAP extends AnvilConnection {

    public AnvilLDAP() {
        super();
    }

    public SearchResultEntry getEntry(String node) {
        try {
            SearchResultEntry entry;

            bind();

            entry = searchEntry(node);

            unbind();

            return entry;
        } catch (ErrorResultException | ErrorResultIOException | SearchResultReferenceIOException e) {
            unbind();
            return null;
        }
    }

    private SearchResultEntry searchEntry(String e) throws ErrorResultIOException, SearchResultReferenceIOException {
        final ConnectionEntryReader reader;
        SearchResultEntry entry = null;

        reader = connection.search(e, SearchScope.WHOLE_SUBTREE, "(objectClass=*)", "*");

        while (reader.hasNext()) {
            entry = reader.readEntry();
            break;
        }

        return entry;
    }

    public LinkedList getEntryTree(String node) {
        try {
            final ConnectionEntryReader reader;
            LinkedList l1 = new LinkedList();

            bind();

            reader = connection.search("", SearchScope.WHOLE_SUBTREE, "(objectClass=*)", "*");

            while (reader.hasNext()) {
                final SearchResultEntry entry = reader.readEntry();
                l1.add(entry);
            }

            unbind();

            return l1;
        } catch (ErrorResultException | ErrorResultIOException | SearchResultReferenceIOException e) {
            unbind();
            System.out.println("something bad happened");
            return null;
        }
    }

    public void addUser(String namingConvention,
            String rootDn,
            String firstName,
            String LastName,
            String commonName,
            String userId,
            String password,
            String email,
            String telephone) throws LDAPActionException {
        try {
            bind();

            String enrtyDN = null;
            switch (namingConvention) {
                case "givenName":
                    enrtyDN = "givenName=" + firstName + "," + rootDn;
                    break;
                case "cn":
                    enrtyDN = "cn=" + commonName + "," + rootDn;
                    break;
                case "sn":
                    enrtyDN = "sn=" + LastName + "," + rootDn;
                    break;
                case "uid":
                    enrtyDN = "uid=" + userId + "," + rootDn;
                    break;
            }

            Entry e = new LinkedHashMapEntry(enrtyDN)
                    .addAttribute("objectclass", "top")
                    .addAttribute("objectclass", "person")
                    .addAttribute("objectclass", "organizationalPerson")
                    .addAttribute("objectclass", "inetOrgPerson")
                    .addAttribute("givenName", firstName)
                    .addAttribute("sn", LastName)
                    .addAttribute("cn", commonName)
                    .addAttribute("uid", userId)
                    .addAttribute("userPassword", password)
                    .addAttribute("mail", email)
                    .addAttribute("telephoneNumber", telephone);

            connection.add(e);

            unbind();
        } catch (ErrorResultException e) {
            throw new LDAPActionException();
        }
    }

    public void addGroup(String rootDN,
            String name,
            String description,
            String... members) throws LDAPActionException {
        try {
            bind();

            String enrtyDN = "cn=" + name + "," + rootDN;

            Entry e = new LinkedHashMapEntry(enrtyDN)
                    .addAttribute("objectclass", "top")
                    .addAttribute("objectclass", "groupOfUniqueNames")
                    .addAttribute("cn", name)
                    .addAttribute("description", description);

            for (String member : members) {
                e.addAttribute("uniqueMember", member);
            }
            
            connection.add(e);

            unbind();
        } catch (ErrorResultException e) {
            throw new LDAPActionException();
        }
    }

    public void addOrganizationalUnit(String rootDN,
            String name,
            String description,
            String address,
            String telephone) throws LDAPActionException {
        try {
            bind();

            String enrtyDN = "ou=" + name + "," + rootDN;

            Entry e = new LinkedHashMapEntry(enrtyDN)
                    .addAttribute("objectclass", "top")
                    .addAttribute("objectclass", "organizationalUnit")
                    .addAttribute("ou", name)
                    .addAttribute("description", description)
                    .addAttribute("postalAddress", address)
                    .addAttribute("telephoneNumber", telephone);

            connection.add(e);

            unbind();
        } catch (ErrorResultException e) {
            throw new LDAPActionException();
        }
    }

    public void addOrganization(String rootDN,
            String name,
            String description) throws LDAPActionException {
        try {
            bind();

            String enrtyDN = "o=" + name + "," + rootDN;

            Entry e = new LinkedHashMapEntry(enrtyDN)
                    .addAttribute("objectclass", "top")
                    .addAttribute("objectclass", "organization")
                    .addAttribute("o", name)
                    .addAttribute("description", description);

            connection.add(e);

            unbind();
        } catch (ErrorResultException e) {
            throw new LDAPActionException();
        }
    }

    public void addDomain(String rootDN,
            String name,
            String description) throws LDAPActionException {
        try {
            bind();

            String enrtyDN = "dc=" + name + "," + rootDN;

            Entry e = new LinkedHashMapEntry(enrtyDN)
                    .addAttribute("objectclass", "top")
                    .addAttribute("objectclass", "domain")
                    .addAttribute("dc", name)
                    .addAttribute("description", description);

            connection.add(e);

            unbind();
        } catch (ErrorResultException e) {
            throw new LDAPActionException();
        }
    }
    
    public void deleteEntry(String entryDN) throws LDAPActionException {
        try {
            bind();

            connection.delete(entryDN);

            unbind();
        } catch (ErrorResultException e) {
            throw new LDAPActionException();
        }
    }
}
